import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;


public class DiscoverServices {
	int port;
	InetAddress hostAddress;
	Socket socket = null;
	Service s;
	BufferedReader reader;
	BufferedWriter writer;
	int timeout = 20;			// 20 ms before timeout when reading a line


	public DiscoverServices(int port, InetAddress hostAddress) {
		this.port = port;
		this.hostAddress = hostAddress;
		this.s = Service.UNKNOWN;
	}

	/**
	 * Tries to establish a connection to a specific URL which consists of an IP adress and a port number.
	 * If a connection exists, the HeaderFields are being read. If one value contains "HTTP", then its definitely a http service.
	 * (Could also be FTP..)
	 * 
	 * @return HTTP service running or not 
	 */
	public boolean discoverHTTP() {
		try {    
			URL url = new URL("http://"+ this.hostAddress.getHostAddress() + ":" + this.port + "/");
			URLConnection c = url.openConnection();
			c.setReadTimeout(400);
			for (int i=0; ; i++) {
				String name = c.getHeaderFieldKey(i);
				String value = c.getHeaderField(i);

				if (name == null && value == null)     // end of headers
					break;         

				if (name == null) {     // first line of headers
					if(value.contains("HTTP")){
						System.out.println("Service reply: " + value);
						return true;
					} else {
						System.out.println(value);
						return false;
					}
				}
				else if(value.contains("HTTP")){
						System.out.println("Service reply: " + value);
						return true;
					}					
			}
			return false;
		} 
		catch (Exception e) {
		}
		return false;
	}

	/**
	 * Connects to a specific address and port number with a socket and reads the first line that is sent by the host.
	 * If the response starts with the value '220', then a FTP service is running on the host.
	 * 
	 * @return FTP service running or not 
	 */
	public boolean discoverFTP() {
		String response = null;
		try {
			socket = new Socket(hostAddress, port);
			socket.setSoTimeout(timeout); // Set the timeout for readLine() method
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

			response = reader.readLine();

			// Closing everything that has been opened
			writer.close();
			reader.close();
			socket.close();
		} catch (IOException e) {
			//System.out.println("No FTP service found for port "+port);
		}

		if (!(response == null) && response.startsWith("220 ")) {
			System.out.println("Service reply: " + response);
			return true;
		}
		return false;
	}
	
	/**
	 * Creates an instance of ReadWithScanner which parses a text-file.
	 * The textfile is being read line by line and the Scanner looks for the given port.
	 * If the port is found, the value is printed out in order to identify the running service.
	 */
	public void discoverWithList() {
		ReadWithScanner parser = new ReadWithScanner("wiki/ports.txt", port);
	    try {
			String service = parser.processLineByLine();
			if(service == null) System.out.println("Unknown service running on this port.");
			else System.out.println(service);
		} catch (FileNotFoundException e) {
			System.out.println("File not found!");
	}
		
	}
}
